﻿using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;

namespace StudyStackFrame
{
    class Program
    {
        static void Main(string[] args)
        {
            //Assembly assembly = Assembly.GetExecutingAssembly();
            //AssemblyVersionAttribute versionAttribute = (AssemblyVersionAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyVersionAttribute));
            //Console.WriteLine(versionAttribute.Version);
            //Console.WriteLine(Environment.Version);
            //Console.WriteLine(Application.);
            //throw new ArgumentNullException("The param is null.");

            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
            Console.WriteLine(Process.GetCurrentProcess().ProcessName);
            //MyMethod();
            //Console.WriteLine(0xff);  //255
            //TestClass testClass = new TestClass();
            ////testClass.TestMethod();
            //testClass.TestMethod("", "");
            //Console.ReadLine();
        }

        private static void MyMethod()
        {
            StackFrame stackFrame = new StackFrame();

            Console.WriteLine(stackFrame.GetMethod().DeclaringType);
            Console.WriteLine(stackFrame.GetMethod().Name);
        }

        private static string BuildStackTrace(Exception exception)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("------------------------");
            stringBuilder.Append(Environment.NewLine);
            stringBuilder.Append(exception.GetType().ToString());
            stringBuilder.Append(Environment.NewLine);
            stringBuilder.Append(EnhancedStackTrace(exception));

            Exception innerException = null;
            while (exception.InnerException != null)
            {
                innerException = exception.InnerException;
                stringBuilder.Append(Environment.NewLine);
                stringBuilder.Append(innerException.GetType().ToString());
                stringBuilder.Append(Environment.NewLine);
                stringBuilder.Append(EnhancedStackTrace(innerException));
            }
            return stringBuilder.ToString();
        }

        private static string EnhancedStackTrace(Exception exception)
        {
            StackTrace stackTrace = new StackTrace(exception, true);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < stackTrace.FrameCount; i++)
            {
                StackFrame stackFrame = stackTrace.GetFrame(i);
                stringBuilder.Append(StackFrameToString(stackFrame));
            }
            stringBuilder.Append(Environment.NewLine);
            return stringBuilder.ToString();
        }

        public static string StackFrameToString(StackFrame stackFrame)
        {
            StringBuilder stringBuilder = new StringBuilder();
            MemberInfo memberInfo = stackFrame.GetMethod();
            stringBuilder.Append("    ");
            if (memberInfo.DeclaringType != null)
            {
                stringBuilder.Append(memberInfo.DeclaringType.Namespace);
                stringBuilder.Append(" . ");
                stringBuilder.Append(memberInfo.DeclaringType.Name);
            }
            stringBuilder.Append(" . ");
            stringBuilder.Append(memberInfo.Name);
            stringBuilder.Append("(");
            foreach (ParameterInfo item in stackFrame.GetMethod().GetParameters())
            {
                stringBuilder.Append(item.ParameterType.Name);
                stringBuilder.Append(" ");
                stringBuilder.Append(item.Name);
            }
            stringBuilder.Append(")");
            stringBuilder.Append(Environment.NewLine);
            stringBuilder.Append("   ");
            if (string.IsNullOrEmpty(stackFrame.GetFileName()))
            {
                stringBuilder.Append(string.Format("{0}", stackFrame.GetNativeOffset()));
            }
            else
            {
                stringBuilder.Append(stackFrame.GetFileName());
                stringBuilder.Append(Path.GetFileName(stackFrame.GetFileName()));
                stringBuilder.Append(": line");
                stringBuilder.Append(stackFrame.GetFileLineNumber());
            }
            return stringBuilder.ToString();
        }
    }

    public class TestClass
    {
        public void TestMethod()
        {
            //第一个是最内层的堆栈信息

            //最后一个是最外层的堆栈信息

            //原来StackTrace里面的堆栈信息也都是通过拼接而来的
            //通过Reflector查看源代码
            //只有想不到的，只有做不到的，继续加油

            StackTrace stackTrace = new StackTrace();
            int stackFrameCount = stackTrace.FrameCount;
            for (int i = 0; i < stackFrameCount; i++)
            {
                StackFrame stackFrame = new StackFrame(i);
                MethodBase methodBase = stackFrame.GetMethod();
                if (methodBase.DeclaringType != null)
                {
                    Console.WriteLine(methodBase.DeclaringType.Namespace);   //命名空间
                    Console.WriteLine(methodBase.DeclaringType.Name);           //类名
                }
                Console.WriteLine(methodBase.Name);                                     //方法名
                Console.WriteLine(stackFrame.GetFileName());
                Console.WriteLine(stackFrame.GetFileLineNumber());


                Console.WriteLine(stackFrame.GetNativeOffset());
                Console.WriteLine("======================================");
            }
        }

        public void TestMethod(string one, string two)
        {
            StackTrace stackTrace = new StackTrace();
            int stackFrameCount = stackTrace.FrameCount;
            for (int i = 0; i < stackFrameCount; i++)
            {
                StackFrame stackFrame = new StackFrame(i);
                MethodBase methodBase = stackFrame.GetMethod();
                if (methodBase.DeclaringType != null)
                {
                    Console.WriteLine(methodBase.DeclaringType.Namespace);   //命名空间
                    Console.WriteLine(methodBase.DeclaringType.Name);           //类名
                    Console.WriteLine(methodBase.DeclaringType.FullName);
                }
                Console.WriteLine(methodBase.Name);                                     //方法名
                //Console.WriteLine(stackFrame.GetFileName());
                //Console.WriteLine(stackFrame.GetFileLineNumber());

                Console.WriteLine("******************************");
                foreach (ParameterInfo parameterInfo in methodBase.GetParameters())  //参数
                {
                    Console.WriteLine(parameterInfo.ParameterType.Name);
                    Console.WriteLine(parameterInfo.Name);
                }
                Console.WriteLine("******************************");

                //Console.WriteLine(stackFrame.GetNativeOffset());
                Console.WriteLine("======================================");
            }
        }
    }
}
